﻿using System.Collections;
using System.IO;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace VoxelBlock.PackMod
{
    /// <summary>
    /// 减小内存的方式读取Voxel
    /// </summary>
    public class ReduceMemoryVoxelToMesh2 : AVoxelToMesh
    {
        //Vector3 localAnchor;
        Vector3 worldAnchor;

        static float verticesEposelong = 0.01f;
        static float uvEposelong = 0.1f;

        class VoxelReadDictionary : IEnumerable
        {
            byte[] mStartIndexXs;
            byte[][] mStartIndexYs;
            byte[] mOverIndexXs;
            byte[][] mOverIndexYs;
            ByteTo8Bool[][][] newDatas;
            int sizeX;
            int sizeY;
            int sizeZ;

            private int count;
            public int Count
            {
                get { return count; }
            }

            public bool this[Vector3Byte v, int index]
            {
                get { return GetValue(v.x, v.y, v.z, index); }
            }

            public bool this[int x, int y, int z, int index]
            {
                get { return GetValue(x, y, z, index); }
            }

            public VoxelReadDictionary(VoxelFileInfo data)
            {

                var voxels = data.Voxels;
                sizeX = data.SizeX;
                sizeY = data.SizeY;
                sizeZ = data.SizeZ;

                mStartIndexXs = new byte[sizeX];
                mStartIndexYs = new byte[sizeX][];

                mOverIndexXs = new byte[sizeX];
                mOverIndexYs = new byte[sizeX][];

                for (int i = 0; i < sizeX; i++)
                {
                    mStartIndexXs[i] = byte.MaxValue;
                    mOverIndexXs[i] = 0;
                }
                for (int x = 0; x < sizeX; x++)
                {
                    mStartIndexYs[x] = new byte[sizeY];
                    mOverIndexYs[x] = new byte[sizeY];
                    for (int y = 0; y < sizeY; y++)
                    {
                        mStartIndexYs[x][y] = byte.MaxValue;
                        mOverIndexYs[x][y] = 0;
                    }
                }
                newDatas = new ByteTo8Bool[sizeX][][];
                for (int x = 0; x < sizeX; x++)
                {
                    int startIndexY = 0;
                    for (int y = 0; y < sizeY; y++)
                    {
                        for (int z = 0; z < sizeZ; z++)
                        {
                            if (voxels[x][y][z] != 255)
                            {
                                startIndexY = y;
                                goto OverLoop1;
                            }
                        }
                    }
                    OverLoop1:

                    int overIndexY = 0;
                    for (int y = sizeY - 1; y >= 0; y--)
                    {
                        for (int z = 0; z < sizeZ; z++)
                        {
                            if (voxels[x][y][z] != 255)
                            {
                                overIndexY = y;
                                goto OverLoop2;
                            }
                        }
                    }
                    OverLoop2:

                    int lengthY = overIndexY - startIndexY + 1;
                    newDatas[x] = new ByteTo8Bool[lengthY][];
                    mStartIndexXs[x] = (byte)startIndexY;
                    mOverIndexXs[x] = (byte)overIndexY;

                    for (int y = 0; y < lengthY; y++)
                    {
                        int startIndexZ = -1;
                        for (int z = 0; z < sizeZ; z++)
                        {
                            if (voxels[x][y + startIndexY][z] != 255)
                            {
                                startIndexZ = z;
                                break;
                            }
                        }

                        int overIndexZ = -1;
                        for (int z = sizeZ - 1; z >= 0; z--)
                        {
                            if (voxels[x][y + startIndexY][z] != 255)
                            {
                                overIndexZ = z;
                                break;
                            }
                        }

                        if (startIndexZ == -1)
                        {
                            newDatas[x][y] = null;
                        }
                        else
                        {

                            int lengthZ = overIndexZ - startIndexZ + 1;
                            newDatas[x][y] = new ByteTo8Bool[lengthZ];
                            mStartIndexYs[x][y + startIndexY] = (byte)startIndexZ;
                            mOverIndexYs[x][y + startIndexY] = (byte)overIndexZ;

                            for (int z = 0; z < lengthZ; z++)
                            {
                                byte zData = voxels[x][y + startIndexY][z + startIndexZ];
                                if (zData == 255)
                                {
                                    newDatas[x][y][z] = new ByteTo8Bool(false);
                                }
                                else
                                {
                                    newDatas[x][y][z] = new ByteTo8Bool(true);
                                    count++;
                                }
                            }
                        }
                    }
                }

            }

            public bool GetValue(int x, int y, int z, int index)
            {
                if (x >= sizeX || y >= sizeY || z >= sizeZ)
                {
                    return false;
                }
                if (mStartIndexXs[x] <= y && y <= mOverIndexXs[x])
                {
                    if (newDatas[x][y - mStartIndexXs[x]] == null)
                    {
                        return false;
                    }
                    if (mStartIndexYs[x][y] <= z && z <= mOverIndexYs[x][y])
                    {
                        return newDatas[x][y - mStartIndexXs[x]][z - mStartIndexYs[x][y]][index];
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }

            public void Remove(int x, int y, int z, int index)
            {
                if (x >= sizeX || y >= sizeY || z >= sizeZ)
                {
                    return;
                }
                if (mStartIndexXs[x] <= y && y <= mOverIndexXs[x])
                {
                    if (newDatas[x][y - mStartIndexXs[x]] == null)
                    {
                        return;
                    }
                    if (mStartIndexYs[x][y] <= z && z <= mOverIndexYs[x][y])
                    {
                        newDatas[x][y - mStartIndexXs[x]][z - mStartIndexYs[x][y]][index] =false;
                        count--;
                        return;
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }

            public void Remove(Vector3Byte v, int index)
            {
                Remove(v.x, v.y, v.z, index);
            }

            public IEnumerator GetEnumerator()
            {
                for (int x = 0, maxX = newDatas.Length; x < maxX; x++)
                {
                    for (int y = 0, maxY = newDatas[x].Length; y < maxY; y++)
                    {
                        if (newDatas[x][y] != null)
                        {
                            for (int z = 0, maxZ = newDatas[x][y].Length; z < maxZ; z++)
                            {
                                //yield return new Vector3Byte(x, y + mStartIndexXs[x], z + mStartIndexYs[x][y + mStartIndexXs[x]]);
                                if (!newDatas[x][y][z].IsAllFalse())
                                {
                                    yield return new Vector3Byte(x, y + mStartIndexXs[x], z + mStartIndexYs[x][y + mStartIndexXs[x]]);
                                }
                            }
                        }
                    }
                }

            }

            public Vector3Byte First()
            {
                if (count > 0)
                {
                    for (int x = 0, maxX = newDatas.Length; x < maxX; x++)
                    {
                        for (int y = 0, maxY = newDatas[x].Length; y < maxY; y++)
                        {
                            if (newDatas[x][y] != null)
                            {
                                for (int z = 0, maxZ = newDatas[x][y].Length; z < maxZ; z++)
                                {
                                    if (!newDatas[x][y][z].IsAllFalse())
                                    {
                                        return new Vector3Byte(x, y + mStartIndexXs[x], z + mStartIndexYs[x][y + mStartIndexXs[x]]);
                                    }
                                }
                            }
                        }
                    }
                }
                return new Vector3Byte(255, 255, 255);
            }
        }

        internal sealed class ReadVoxelToSurface
        {


            ByteTo8Bool[] isReadVoxels;
            //bool[] isReadVoxelsRight;
            //bool[] isReadVoxelsLeft;
            //bool[] isReadVoxelsUp;
            //bool[] isReadVoxelsDown;
            //bool[] isReadVoxelsFront;
            //bool[] isReadVoxelsBreak;
            Color32[] allColor;
            byte[] voxelBytes;

            int sizeYZ;
            int sizeZ_1;
            int sizeY_1;
            int sizeX_1;

            public ReadVoxelToSurface(int sizeX, int sizeY, int sizeZ, byte[] allVoxels, Color32[] allColor)
            {
                this.sizeX = sizeX;
                this.sizeY = sizeY;
                this.sizeZ = sizeZ;
                this.allColor = allColor;
                voxelBytes = allVoxels;

                sizeYZ = sizeZ * sizeY;
                sizeZ_1 = sizeZ - 1;
                sizeY_1 = sizeY - 1;
                sizeX_1 = sizeX - 1;
                isReadVoxels = new ByteTo8Bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsRight = new bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsLeft = new bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsUp = new bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsDown = new bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsFront = new bool[sizeX * sizeY * sizeZ];
                //isReadVoxelsBreak = new bool[sizeX * sizeY * sizeZ];
            }

            public int GetIndex(int x, int y, int z)
            {
                return x * sizeYZ + (sizeZ_1 - z) * sizeY + (sizeY_1 - y);
            }
            public int GetUpId(int id)
            {
                return id - 1;
            }
            public int GetDownId(int id)
            {
                return id + 1;
            }
            public int GetRightId(int id)
            {
                return id + sizeYZ;
            }
            public int GetLeftId(int id)
            {
                return id - sizeYZ;
            }
            public int GetFrontId(int id)
            {
                return id - sizeY;
            }
            public int GetBreakId(int id)
            {
                return id + sizeY;
            }

            public bool IsUp(int id)
            {
                if (voxelBytes[id - 1] == 255)
                {
                    return true;
                }
                return false;
            }
            public bool IsDown(int id)
            {
                if (voxelBytes[id + 1] == 255)
                {
                    return true;
                }
                return false;
            }
            public bool IsRight(int id)
            {
                if (voxelBytes[id + sizeYZ] == 255)
                {
                    return true;
                }
                return false;
            }
            public bool IsLeft(int id)
            {
                if (voxelBytes[id - sizeYZ] == 255)
                {
                    return true;
                }
                return false;
            }
            public bool IsFront(int id)
            {
                if (voxelBytes[id - sizeY] == 255)
                {
                    return true;
                }
                return false;
            }
            public bool IsBreak(int id)
            {
                if (voxelBytes[id + sizeY] == 255)
                {
                    return true;
                }
                return false;
            }

            public byte GetUp(int id)
            {
                return voxelBytes[id - 1];
            }
            public byte GetDown(int id)
            {
                return voxelBytes[id + 1];
            }
            public byte GetRight(int id)
            {
                return voxelBytes[id + sizeYZ];
            }
            public byte GetLeft(int id)
            {
                return voxelBytes[id - sizeYZ];
            }
            public byte GetFront(int id)
            {
                return voxelBytes[id - sizeY];
            }
            public byte GetBreak(int id)
            {
                return voxelBytes[id + sizeY];
            }

            readonly int sizeX;
            readonly int sizeY;
            readonly int sizeZ;

            public List<VoxelSurfaceData> UpSurfaceData;
            public List<VoxelSurfaceData> DownSurfaceData;
            public List<VoxelSurfaceData> RightSurfaceData;
            public List<VoxelSurfaceData> LeftSurfaceData;
            public List<VoxelSurfaceData> BreakSurfaceData;
            public List<VoxelSurfaceData> FrontSurfaceData;
            public int allVoxelSurfaceSize;

            public void Read()
            {
                allVoxelSurfaceSize = 0;
                UpSurfaceData = new List<VoxelSurfaceData>();
                DownSurfaceData = new List<VoxelSurfaceData>();
                RightSurfaceData = new List<VoxelSurfaceData>();
                LeftSurfaceData = new List<VoxelSurfaceData>();
                BreakSurfaceData = new List<VoxelSurfaceData>();
                FrontSurfaceData = new List<VoxelSurfaceData>();
                bool borderUp;
                bool borderDown;
                bool borderRight;
                bool borderLeft;
                bool borderBreak;
                bool borderFront;
                for (int x = 0, id = 0; x < sizeX; x++)
                {
                    if (x == 0)
                    {
                        borderLeft = true;
                    }
                    else
                    {
                        borderLeft = false;
                    }
                    if (x == sizeX_1)
                    {
                        borderRight = true;
                    }
                    else
                    {
                        borderRight = false;
                    }
                    for (int z = sizeZ_1; z >= 0; z--)
                    {
                        if (z == sizeZ_1)
                        {
                            borderFront = true;
                        }
                        else
                        {
                            borderFront = false;
                        }
                        if (z == 0)
                        {
                            borderBreak = true;
                        }
                        else
                        {
                            borderBreak = false;
                        }
                        for (int y = sizeY_1; y >= 0; y--, id++)
                        {
                            if (voxelBytes[id] != 255)
                            {
                                if (y == sizeY_1)
                                {
                                    borderUp = true;
                                }
                                else
                                {
                                    borderUp = false;
                                }
                                if (y == 0)
                                {
                                    borderDown = true;
                                }
                                else
                                {
                                    borderDown = false;
                                }
                                if ((borderUp || IsUp(id)) && !isReadVoxels[id][0])
                                {
                                    int lengthZ = ReadLineUp(borderUp, y, z, id);
                                    int lengthX = ReadSurfaceUp(borderUp, x, z, id, lengthZ);
                                    Color32[] colors = new Color32[lengthZ * lengthX];

                                    int loopZid = GetIndex(x, y, z - lengthZ + 1);
                                    for (int loopZ = 0, colorIndex = 0; loopZ < lengthZ; loopZ++)
                                    //for (int loopZ = z, maxZ = z + lengthZ, maxX = x + lengthX, colorIndex = 0; loopZ < maxZ; loopZ++)
                                    {
                                        int loopXid = loopZid;
                                        for (int loopX = 0; loopX < lengthX; loopX++, colorIndex++)
                                        {
                                            isReadVoxels[loopXid][0] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopXid]];
                                            loopXid = GetRightId(loopXid);
                                        }
                                        loopZid = GetFrontId(loopZid);
                                    }
                                    allVoxelSurfaceSize += lengthZ * lengthX;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(x, z - lengthZ + 1, lengthX, lengthZ, y, colors);
                                    UpSurfaceData.Add(surfaceData);

                                }
                                if ((borderDown || IsDown(id)) && !isReadVoxels[id][1])
                                {
                                    int lengthZ = ReadLineDown(borderDown, y, z, id);
                                    int lengthX = ReadSurfaceDown(borderDown, x, z, id, lengthZ);
                                    Color32[] colors = new Color32[lengthZ * lengthX];

                                    int loopZid = id;
                                    for (int loopZ = 0, colorIndex = 0; loopZ < lengthZ; loopZ++)
                                    {
                                        int loopXid = loopZid;
                                        for (int loopX = 0; loopX < lengthX; loopX++, colorIndex++)
                                        {
                                            isReadVoxels[loopXid][1] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopXid]];
                                            loopXid = GetRightId(loopXid);
                                        }
                                        loopZid = GetBreakId(loopZid);
                                    }
                                    allVoxelSurfaceSize += lengthZ * lengthX;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(x, z - lengthZ + 1, lengthX, lengthZ, y, colors);
                                    DownSurfaceData.Add(surfaceData);
                                }
                                if ((borderFront || IsFront(id)) && !isReadVoxels[id][2])
                                {
                                    int lengthX = ReadLineFront(borderFront, x, id);
                                    int lengthY = ReadSurfaceFront(borderFront, x, y, id, lengthX);

                                    Color32[] colors = new Color32[lengthX * lengthY];

                                    int loopYid = GetIndex(x + lengthX - 1, y - lengthY + 1, z);
                                    for (int loopY = 0, colorIndex = 0; loopY < lengthY; loopY++)
                                    {
                                        int loopXid = loopYid;
                                        for (int loopX = 0; loopX < lengthX; loopX++, colorIndex++)
                                        {
                                            isReadVoxels[loopXid][2] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopXid]];
                                            loopXid = GetLeftId(loopXid);
                                        }
                                        loopYid = GetUpId(loopYid);
                                    }
                                    allVoxelSurfaceSize += lengthX * lengthY;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(x, y - lengthY + 1, lengthX, lengthY, z, colors);
                                    FrontSurfaceData.Add(surfaceData);
                                }
                                if ((borderBreak || IsBreak(id)) && !isReadVoxels[id][3])
                                {
                                    int lengthX = ReadLineBreak(borderBreak, x, id);
                                    int lengthY = ReadSurfaceBreak(borderBreak, y, id, lengthX);

                                    Color32[] colors = new Color32[lengthX * lengthY];
                                    int loopYid = GetIndex(x, y - lengthY + 1, z);
                                    for (int loopY = 0, colorIndex = 0; loopY < lengthY; loopY++)
                                    {
                                        int loopXid = loopYid;
                                        for (int loopX = 0; loopX < lengthX; loopX++, colorIndex++)
                                        {
                                            isReadVoxels[loopXid][3] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopXid]];
                                            loopXid = GetRightId(loopXid);
                                        }
                                        loopYid = GetUpId(loopYid);
                                    }
                                    allVoxelSurfaceSize += lengthX * lengthY;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(x, y - lengthY + 1, lengthX, lengthY, z, colors);
                                    BreakSurfaceData.Add(surfaceData);
                                }
                                if ((borderRight || IsRight(id)) && !isReadVoxels[id][4])
                                {
                                    int lengthY = ReadLineRight(borderRight, y, id);
                                    int lengthZ = ReadSurfaceRight(borderRight, z, id, lengthY);

                                    Color32[] colors = new Color32[lengthY * lengthZ];

                                    int loopYid = GetIndex(x, y - lengthY + 1, z - lengthZ + 1);
                                    for (int loopY = 0, colorIndex = 0; loopY < lengthY; loopY++)
                                    {
                                        int loopZid = loopYid;
                                        for (int loopZ = 0; loopZ < lengthZ; loopZ++, colorIndex++)
                                        {
                                            isReadVoxels[loopZid][4] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopZid]];
                                            loopZid = GetFrontId(loopZid);
                                        }
                                        loopYid = GetUpId(loopYid);
                                    }
                                    allVoxelSurfaceSize += lengthY * lengthZ;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(z - lengthZ + 1, y - lengthY + 1, lengthZ, lengthY, x, colors);
                                    RightSurfaceData.Add(surfaceData);
                                }
                                if ((borderLeft || IsLeft(id)) && !isReadVoxels[id][5])
                                {
                                    int lengthY = ReadLineLeft(borderLeft, y, id);
                                    int lengthZ = ReadSurfaceLeft(borderLeft, z, id, lengthY);

                                    Color32[] colors = new Color32[lengthY * lengthZ];

                                    int loopYid = GetIndex(x, y - lengthY + 1, z);
                                    for (int loopY = 0, colorIndex = 0; loopY < lengthY; loopY++)
                                    {
                                        int loopZid = loopYid;
                                        for (int loopZ = 0; loopZ < lengthZ; loopZ++, colorIndex++)
                                        {
                                            isReadVoxels[loopZid][5] = true;
                                            colors[colorIndex] = allColor[voxelBytes[loopZid]];
                                            loopZid = GetBreakId(loopZid);
                                        }
                                        loopYid = GetUpId(loopYid);
                                    }
                                    allVoxelSurfaceSize += lengthY * lengthZ;

                                    if (allVoxelSurfaceSize >= VoxelCategories.MAX_SURFACE_SIZE)
                                    {
                                        return;
                                    }
                                    VoxelSurfaceData surfaceData = new VoxelSurfaceData(z - lengthZ + 1, y - lengthY + 1, lengthZ, lengthY, x, colors);
                                    LeftSurfaceData.Add(surfaceData);
                                }
                            }
                        }
                    }
                }

            }

            #region Up

            /// <summary>
            /// 获得一行的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            private int ReadLineUp(bool borderUp, int y, int z, int index)
            {
                int lengthZ = 1;
                int id = GetBreakId(index);
                for (int loopz = z - 1; loopz >= 0; loopz--)
                //for (int loopz = z + 1; loopz < sizeZ; loopz++)
                {
                    if (voxelBytes[id] != 255 && (borderUp || IsUp(id)) && !isReadVoxels[id][0])
                    {
                        lengthZ++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetBreakId(id);
                }
                return lengthZ;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceUp(bool borderUp, int x, int z, int index, int lengthZ)
            {
                int lengthX = 1;
                //int id = index;
                //int maxZ = z - lengthZ;

                int loopXid = GetRightId(index);
                for (int loopx = x + 1; loopx < sizeX; loopx++)
                {
                    int loopZid = loopXid;
                    for (int loopz = z; loopz > z - lengthZ; loopz--)
                    //for (int loopz = z; loopz < lengthZ + z; loopz++)
                    //for (int loopz = z; loopz < maxZ; loopz++)
                    {
                        if (voxelBytes[loopZid] != 255 && (borderUp || IsUp(loopZid)) && !isReadVoxels[loopZid][0])
                        {
                        }
                        else
                        {
                            return lengthX;
                        }
                        loopZid = GetBreakId(loopZid);
                    }
                    lengthX++;
                    loopXid = GetRightId(loopXid);
                }
                return lengthX;
            }
            #endregion

            #region Down

            /// <summary>
            /// 获得一行的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            private int ReadLineDown(bool borderDown, int y, int z, int index)
            {
                int lengthZ = 1;
                int id = GetBreakId(index);
                for (int loopz = z - 1; loopz >= 0; loopz--)
                {
                    if (voxelBytes[id] != 255 && (borderDown || IsDown(id)) && !isReadVoxels[id][1])
                    {
                        lengthZ++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetBreakId(id);
                }
                return lengthZ;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceDown(bool borderDown, int x, int z, int index, int lengthZ)
            {
                int lengthX = 1;

                int loopXid = GetRightId(index);
                for (int loopx = x + 1; loopx < sizeX; loopx++)
                {
                    int loopZid = loopXid;
                    for (int loopz = 0; loopz < lengthZ; loopz++)
                    {
                        if (voxelBytes[loopZid] != 255 && (borderDown || IsDown(loopZid)) && !isReadVoxels[loopZid][1])
                        {
                        }
                        else
                        {
                            return lengthX;
                        }
                        loopZid = GetBreakId(loopZid);
                    }
                    lengthX++;
                    loopXid = GetRightId(loopXid);
                }
                return lengthX;
            }

            #endregion
            #region Front
            /// <summary>
            /// 获得一行的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            private int ReadLineFront(bool borderFront, int x, int index)
            {
                int lengthX = 1;
                int id = GetRightId(index);
                for (int loopx = x + 1; loopx < sizeX; loopx++)
                {
                    if (voxelBytes[id] != 255 && (borderFront || IsFront(id)) && !isReadVoxels[id][2])
                    {
                        lengthX++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetRightId(id);
                }
                return lengthX;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceFront(bool borderFront, int x, int y, int index, int lengthX)
            {
                int lengthY = 1;

                int loopYid = GetDownId(index);
                for (int loopy = y - 1; loopy > 0; loopy--)
                //for (int loopy = y + 1, maxX = lengthX + x; loopy < sizeY; loopy++)
                {
                    int loopXid = loopYid;
                    for (int loopx = x; loopx < x + lengthX; loopx++)
                    //for (int loopx = x; loopx < maxX; loopx++)
                    {
                        if (voxelBytes[loopXid] != 255 && (borderFront || IsFront(loopXid)) && !isReadVoxels[loopXid][2])
                        //if (ReadOnlyVoxels[loopx, loopy, z] != 255 && IsFront(loopx, loopy, z) && !IsReadFront(loopx, loopy, z))
                        {

                        }
                        else
                        {
                            return lengthY;
                        }
                        loopXid = GetRightId(loopXid);
                    }
                    lengthY++;
                    loopYid = GetDownId(loopYid);
                }
                return lengthY;
            }
            #endregion

            #region Break

            /// <summary>
            /// 获得一行的长度
            /// </summary>
            private int ReadLineBreak(bool borderBreak, int x, int index)
            {
                int lengthX = 1;
                int id = GetRightId(index);
                for (int loopx = x + 1; loopx < sizeX; loopx++)
                {
                    if (voxelBytes[id] != 255 && (borderBreak || IsBreak(id)) && !isReadVoxels[id][3])
                    {
                        lengthX++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetRightId(id);
                }
                return lengthX;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceBreak(bool borderBreak, int y, int index, int lengthX)
            {
                int lengthY = 1;

                int loopYid = GetDownId(index);
                for (int loopy = y - 1; loopy >= 0; loopy--)
                {
                    int loopXid = loopYid;
                    for (int loopx = 0; loopx < lengthX; loopx++)
                    {
                        if (voxelBytes[loopXid] != 255 && (borderBreak || IsBreak(loopXid)) && !isReadVoxels[loopXid][3])
                        {
                        }
                        else
                        {
                            return lengthY;
                        }
                        loopXid = GetRightId(loopXid);
                    }
                    lengthY++;
                    loopYid = GetDownId(loopYid);
                }
                return lengthY;
            }
            #endregion

            #region Right
            /// <summary>
            /// 获得一行的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            private int ReadLineRight(bool borderRight, int y, int index)
            {
                int lengthY = 1;
                int id = GetDownId(index);
                for (int loopy = y - 1; loopy > 0; loopy--)
                {
                    if (voxelBytes[id] != 255 && (borderRight || IsRight(id)) && !isReadVoxels[id][4])
                    {
                        lengthY++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetDownId(id);
                }
                return lengthY;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceRight(bool borderRight, int z, int index, int lengthY)
            {
                int lengthZ = 1;
                int loopZid = GetBreakId(index);
                for (int loopz = z - 1; loopz >= 0; loopz--)
                {
                    int loopYid = loopZid;
                    for (int loopy = 0; loopy < lengthY; loopy++)
                    {
                        if (voxelBytes[loopYid] != 255 && (borderRight || IsRight(loopYid)) && !isReadVoxels[loopYid][4])
                        {
                        }
                        else
                        {
                            return lengthZ;
                        }
                        loopYid = GetDownId(loopYid);
                    }
                    lengthZ++;
                    loopZid = GetBreakId(loopZid);
                }
                return lengthZ;
            }
            #endregion


            #region Left
            /// <summary>
            /// 获得一行的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            private int ReadLineLeft(bool borderLeft, int y, int index)
            {
                int lengthY = 1;
                int id = GetDownId(index);
                for (int loopy = y - 1; loopy > 0; loopy--)
                {
                    if (voxelBytes[id] != 255 && (borderLeft || IsLeft(id)) && !isReadVoxels[id][5])
                    {
                        lengthY++;
                    }
                    else
                    {
                        break;
                    }
                    id = GetDownId(id);
                }
                return lengthY;
            }

            /// <summary>
            /// 获得一片的长度
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <param name="lengthZ"></param>
            /// <returns></returns>
            private int ReadSurfaceLeft(bool borderLeft, int z, int index, int lengthY)
            {
                int lengthZ = 1;
                int loopZid = GetBreakId(index);
                for (int loopz = z - 1; loopz >= 0; loopz--)
                {
                    int loopYid = loopZid;
                    for (int loopy = 0; loopy < lengthY; loopy++)
                    {
                        if (voxelBytes[loopYid] != 255 && (borderLeft || IsLeft(loopYid)) && !isReadVoxels[loopYid][5])
                        {
                        }
                        else
                        {
                            return lengthZ;
                        }
                        loopYid = GetDownId(loopYid);
                    }
                    lengthZ++;
                    loopZid = GetBreakId(loopZid);
                }
                return lengthZ;
            }
            #endregion
        }


        List<VoxelSurfaceData> bufferAllSurfaceDatas = new List<VoxelSurfaceData>(1024);
        int bufferAllVoxelSurfaceSize = 0;
        int bufferAllAddTextureSize = 0;

        public override MyMesh GetMeshOrTexture(byte[] aByteData, out MyTexture2D myTexture2D, Vector3 localAnchor)
        {
            Color32[] mainColors;
            int SizeX, SizeY, SizeZ;
            SizeX = aByteData[0];
            SizeZ = aByteData[4];
            SizeY = aByteData[8];

            int maxVoxelSize = SizeX * SizeY * SizeZ;
            byte[] voxelBytes = new byte[maxVoxelSize];
            Array.Copy(aByteData, 12, voxelBytes, 0, maxVoxelSize);
            mainColors = new Color32[256];

            for (int i = 0, colorIndex = 12 + maxVoxelSize; i < 256; i++)
            {
                byte r = aByteData[colorIndex];
                byte g = aByteData[colorIndex + 1];
                byte b = aByteData[colorIndex + 2];
                colorIndex += 3;

                byte R = (byte)(r * 4);
                byte G = (byte)(g * 4);
                byte B = (byte)(b * 4);
                Color32 color = new Color32(R, G, B, 255);
                mainColors[i] = color;
            }

            ReadVoxelToSurface fm_ReadVoxelToSurface = new ReadVoxelToSurface(SizeX, SizeY, SizeZ, voxelBytes, mainColors);

            Vector3[] vertices;
            Vector2[] uvs;
            int[] triangles;

            fm_ReadVoxelToSurface.Read();
            int maxVoxelSurfaceSize = fm_ReadVoxelToSurface.allVoxelSurfaceSize;

            if (maxVoxelSurfaceSize == 0)
            {
                MyMesh overMesh = new MyMesh();
                overMesh.vertices = new Vector3[0];
                overMesh.triangles = new int[0];
                overMesh.uv = new Vector2[0];

                myTexture2D = new MyTexture2D(0, 0);
                return overMesh;
            }

            List<VoxelSurfaceData> allSurfaceDatas = new List<VoxelSurfaceData>(1024);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.RightSurfaceData);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.LeftSurfaceData);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.UpSurfaceData);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.DownSurfaceData);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.BreakSurfaceData);
            allSurfaceDatas.AddRange(fm_ReadVoxelToSurface.FrontSurfaceData);

            worldAnchor = new Vector3(-SizeX * localAnchor.x, -SizeY * localAnchor.y, -SizeZ * localAnchor.z);

            vertices = new Vector3[fm_ReadVoxelToSurface.RightSurfaceData.Count * 4 + fm_ReadVoxelToSurface.LeftSurfaceData.Count * 4 + fm_ReadVoxelToSurface.UpSurfaceData.Count * 4 + fm_ReadVoxelToSurface.DownSurfaceData.Count * 4 + fm_ReadVoxelToSurface.BreakSurfaceData.Count * 4 + fm_ReadVoxelToSurface.FrontSurfaceData.Count * 4];
            int verticesIndex = 0;
            GetVerticesRight(vertices, fm_ReadVoxelToSurface.RightSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.RightSurfaceData.Count * 4;

            GetVerticesLeft(vertices, fm_ReadVoxelToSurface.LeftSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.LeftSurfaceData.Count * 4;

            GetVerticesUp(vertices, fm_ReadVoxelToSurface.UpSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.UpSurfaceData.Count * 4;

            GetVerticesDown(vertices, fm_ReadVoxelToSurface.DownSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.DownSurfaceData.Count * 4;

            GetVerticesBreak(vertices, fm_ReadVoxelToSurface.BreakSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.BreakSurfaceData.Count * 4;

            GetVerticesFront(vertices, fm_ReadVoxelToSurface.FrontSurfaceData, verticesIndex);
            //verticesIndex += fm_ReadVoxelToSurface.FrontSurfaceData.Count * 4;



            int maxHeigth;
            List<VoxelSurfaceData> oneWList;
            VoxelSurfaceData[] overAllSurfaceList = DescendingVoxelSurfaceData(allSurfaceDatas, out maxHeigth, out oneWList);


            int var_mi = (int)(Mathf.Log(maxVoxelSurfaceSize, 2) / 2 + 1);



            int overHeigth = (int)Mathf.Pow(2, var_mi);
            if (overHeigth < maxHeigth)
            {
                overHeigth = maxHeigth;
            }
            if (overHeigth <= 0)
            {
                overHeigth = 1;
            }

            int allW = oneWList.Count / overHeigth;
            if (allW == 0)
            {
                for (int i = 0, length = oneWList.Count; i < length; i++)
                {
                    VoxelSurfaceData surface = oneWList[i];
                    surface.x = 0;
                    surface.y = i;
                }
            }
            else
            {
                int lostHlength = oneWList.Count - overHeigth * (allW);
                for (int w = 0; w < allW; w++)
                {
                    for (int i = 0, length = overHeigth; i < length; i++)
                    {
                        VoxelSurfaceData surface = oneWList[i + w * overHeigth];
                        surface.x = w;
                        surface.y = i;
                    }
                }
                int overLostW = allW;
                for (int i = overHeigth * (allW), indexY = 0, length = overHeigth * (allW) + lostHlength; i < length; i++, indexY++)
                {
                    VoxelSurfaceData surface = oneWList[i];
                    surface.x = overLostW;
                    surface.y = indexY;
                }

            }

            int loopWidth;
            if (overAllSurfaceList.Length > 0)
            {
                loopWidth = overAllSurfaceList[0].w + allW + 1;
                List<MergeImgColumn> imgColumns = new List<MergeImgColumn>();
                imgColumns.Add(new MergeImgColumn(overAllSurfaceList[0], overHeigth, allW + 1));
                for (int i = 1, length = overAllSurfaceList.Length; i < length; i++)
                {
                    VoxelSurfaceData surface = overAllSurfaceList[i];
                    bool isok = false;
                    foreach (MergeImgColumn column in imgColumns)
                    {
                        if (column.AddSurfaceData(surface))
                        {
                            isok = true;
                            break;
                        }
                    }
                    if (!isok)
                    {
                        imgColumns.Add(new MergeImgColumn(surface, overHeigth, loopWidth));
                        loopWidth += surface.w;
                    }
                }

            }
            else
            {
                loopWidth = allW;
            }


            int overWidth = 1;
            while (overWidth < loopWidth)
            {
                overWidth *= 2;
            }

            oneWList.AddRange(overAllSurfaceList);
            uvs = GetUVs(oneWList, overWidth, overHeigth);
            triangles = VoxelMetadata3D.Instance.GetTris(oneWList.Count);

            MyMesh mesh = new MyMesh();
            mesh.vertices = vertices;
            mesh.triangles = triangles;
            mesh.uv = uvs;

            myTexture2D = new MyTexture2D(overWidth, overHeigth);
            for (int x = 0; x < overWidth; x++)
            {
                for (int y = 0; y < overHeigth; y++)
                {
                    myTexture2D.SetPixel(x, y, Color.red);
                }
            }

            for (int i = 0, length = oneWList.Count; i < length; i++)
            {
                VoxelSurfaceData surface = oneWList[i];
                var key = new Vector2Int(surface.x, surface.y);
                for (int x = 0; x < surface.w; x++)
                {
                    for (int y = 0; y < surface.h; y++)
                    {
                        myTexture2D.SetPixel(surface.x + x, surface.y + y, surface.colors[x + y * surface.w]);
                    }
                }
            }

            return mesh;
        }

        /// <summary>
        /// 添加一个voxel数据，并将面的数据添加到图片缓冲区，获得顶点数据
        /// </summary>
        /// <param name="voxelDatas">voxel数据</param>
        /// <returns>顶点数据</returns>
        public override Vector3[] GetVertices(byte[] voxelDatas, Vector3 localAnchor)
        {
            Color32[] mainColors;
            int SizeX, SizeY, SizeZ;
            SizeX = voxelDatas[0];
            SizeZ = voxelDatas[4];
            SizeY = voxelDatas[8];

            int maxVoxelSize = SizeX * SizeY * SizeZ;
            byte[] voxelBytes = new byte[maxVoxelSize];
            Array.Copy(voxelDatas, 12, voxelBytes, 0, maxVoxelSize);

            mainColors = new Color32[256];
            for (int i = 0, colorIndex = 12 + maxVoxelSize; i < 256; i++)
            {
                byte r = voxelDatas[colorIndex];
                byte g = voxelDatas[colorIndex + 1];
                byte b = voxelDatas[colorIndex + 2];
                colorIndex += 3;

                byte R = (byte)(r * 4);
                byte G = (byte)(g * 4);
                byte B = (byte)(b * 4);
                Color32 color = new Color32(R, G, B, 255);
                mainColors[i] = color;
            }

            ReadVoxelToSurface fm_ReadVoxelToSurface = new ReadVoxelToSurface(SizeX, SizeY, SizeZ, voxelBytes, mainColors);

            Vector3[] vertices;

            fm_ReadVoxelToSurface.Read();

            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.RightSurfaceData);
            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.LeftSurfaceData);
            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.UpSurfaceData);
            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.DownSurfaceData);
            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.BreakSurfaceData);
            bufferAllSurfaceDatas.AddRange(fm_ReadVoxelToSurface.FrontSurfaceData);

            worldAnchor = new Vector3(SizeX * localAnchor.x, SizeY * localAnchor.y, SizeZ * localAnchor.z);

            vertices = new Vector3[fm_ReadVoxelToSurface.RightSurfaceData.Count * 4 + fm_ReadVoxelToSurface.LeftSurfaceData.Count * 4 + fm_ReadVoxelToSurface.UpSurfaceData.Count * 4 + fm_ReadVoxelToSurface.DownSurfaceData.Count * 4 + fm_ReadVoxelToSurface.BreakSurfaceData.Count * 4 + fm_ReadVoxelToSurface.FrontSurfaceData.Count * 4];
            int verticesIndex = 0;
            GetVerticesRight(vertices, fm_ReadVoxelToSurface.RightSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.RightSurfaceData.Count * 4;

            GetVerticesLeft(vertices, fm_ReadVoxelToSurface.LeftSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.LeftSurfaceData.Count * 4;

            GetVerticesUp(vertices, fm_ReadVoxelToSurface.UpSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.UpSurfaceData.Count * 4;

            GetVerticesDown(vertices, fm_ReadVoxelToSurface.DownSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.DownSurfaceData.Count * 4;

            GetVerticesBreak(vertices, fm_ReadVoxelToSurface.BreakSurfaceData, verticesIndex);
            verticesIndex += fm_ReadVoxelToSurface.BreakSurfaceData.Count * 4;

            GetVerticesFront(vertices, fm_ReadVoxelToSurface.FrontSurfaceData, verticesIndex);

            bufferAllVoxelSurfaceSize += fm_ReadVoxelToSurface.allVoxelSurfaceSize;
            return vertices;
        }

        /// <summary>
        /// 添加一张图片到图片缓冲区
        /// </summary>
        /// <param name="texture"></param>
        public override void AddTexture(Texture2D texture)
        {
            var data = new VoxelSurfaceData(0, 0, texture.width, texture.height, 0, texture.GetPixels32());
            data.index = -1;
            bufferAllAddTextureSize++;
            bufferAllSurfaceDatas.Add(data);
        }

        /// <summary>
        /// 添加一张图片到图片缓冲区
        /// </summary>
        /// <param name="texture"></param>
        public override void AddTexture(MyTexture2D texture)
        {
            var data = new VoxelSurfaceData(0, 0, texture.width, texture.height, 0, texture.GetPixels32());
            data.index = -1;
            bufferAllAddTextureSize++;
            bufferAllSurfaceDatas.Add(data);
        }

        /// <summary>
        /// 合并所有图片缓冲区的数据 ， 并获得三角面和UV信息
        /// </summary>
        /// <returns></returns>
        public override MyTexture2D Over(out int[] triangles, out Vector2[] uv)
        {
            int maxHeigth;
            List<VoxelSurfaceData> oneWList;
            VoxelSurfaceData[] overAllSurfaceList = DescendingVoxelSurfaceData(bufferAllSurfaceDatas, out maxHeigth, out oneWList);


            int maxVoxelSurfaceSize = bufferAllVoxelSurfaceSize;
            int var_mi = (int)(Mathf.Log(maxVoxelSurfaceSize, 2) / 2 + 1);


            int overHeigth = (int)Mathf.Pow(2, var_mi);
            if (overHeigth < maxHeigth)
            {
                overHeigth = maxHeigth;
            }
            if (overHeigth <= 0)
            {
                overHeigth = 1;
            }

            int allW = oneWList.Count / overHeigth;
            if (allW == 0)
            {
                for (int i = 0, length = oneWList.Count; i < length; i++)
                {
                    VoxelSurfaceData surface = oneWList[i];
                    surface.x = 0;
                    surface.y = i;
                }
            }
            else
            {
                int lostHlength = oneWList.Count - overHeigth * (allW);
                for (int w = 0; w < allW; w++)
                {
                    for (int i = 0, length = overHeigth; i < length; i++)
                    {
                        VoxelSurfaceData surface = oneWList[i + w * overHeigth];
                        surface.x = w;
                        surface.y = i;
                    }
                }
                int overLostW = allW;
                for (int i = overHeigth * (allW), indexY = 0, length = overHeigth * (allW) + lostHlength; i < length; i++, indexY++)
                {
                    VoxelSurfaceData surface = oneWList[i];
                    surface.x = overLostW;
                    surface.y = indexY;
                }

            }

            int loopWidth;
            if (overAllSurfaceList.Length > 0)
            {
                loopWidth = overAllSurfaceList[0].w + allW;
                List<MergeImgColumn> imgColumns = new List<MergeImgColumn>();
                imgColumns.Add(new MergeImgColumn(overAllSurfaceList[0], overHeigth, allW + 1));
                for (int i = 1, length = overAllSurfaceList.Length; i < length; i++)
                {
                    VoxelSurfaceData surface = overAllSurfaceList[i];
                    bool isok = false;
                    foreach (MergeImgColumn column in imgColumns)
                    {
                        if (column.AddSurfaceData(surface))
                        {
                            isok = true;
                            break;
                        }
                    }
                    if (!isok)
                    {
                        imgColumns.Add(new MergeImgColumn(surface, overHeigth, loopWidth));
                        loopWidth += surface.w;
                    }
                }

            }
            else
            {
                loopWidth = allW;
            }


            int overWidth = 1;
            while (overWidth < loopWidth)
            {
                overWidth *= 2;
            }

            oneWList.AddRange(overAllSurfaceList);
            uv = GetUVs(oneWList, overWidth, overHeigth);
            triangles = VoxelMetadata3D.Instance.GetTris(oneWList.Count);


            MyTexture2D myTexture2D = new MyTexture2D(overWidth, overHeigth);
            for (int x = 0; x < overWidth; x++)
            {
                for (int y = 0; y < overHeigth; y++)
                {
                    myTexture2D.SetPixel(x, y, Color.red);
                }
            }

            for (int i = 0, length = oneWList.Count; i < length; i++)
            {
                VoxelSurfaceData surface = oneWList[i];
                var key = new Vector2Int(surface.x, surface.y);
                for (int x = 0; x < surface.w; x++)
                {
                    for (int y = 0; y < surface.h; y++)
                    {
                        myTexture2D.SetPixel(surface.x + x, surface.y + y, surface.colors[x + y * surface.w]);
                    }
                }
            }


            return myTexture2D;
        }

        void GetVerticesRight(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z + 1;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;

                vertices[verticesIndex] = new Vector3(z, maxY + verticesEposelong, surface.x - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(z, maxY + verticesEposelong, maxX + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(z, surface.y - verticesEposelong, maxX + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(z, surface.y - verticesEposelong, surface.x - verticesEposelong) + worldAnchor;
            }
        }

        void GetVerticesLeft(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;

                vertices[verticesIndex] = new Vector3(z, maxY + verticesEposelong, maxX + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(z, maxY + verticesEposelong, surface.x - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(z, surface.y - verticesEposelong, surface.x - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(z, surface.y - verticesEposelong, maxX + verticesEposelong) + worldAnchor;
            }
        }

        void GetVerticesUp(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z + 1;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;
                vertices[verticesIndex] = new Vector3(surface.x - verticesEposelong, z, maxY + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(maxX + verticesEposelong, z, maxY + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(maxX + verticesEposelong, z, surface.y - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(surface.x - verticesEposelong, z, surface.y - verticesEposelong) + worldAnchor;
            }
        }

        void GetVerticesDown(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;
                vertices[verticesIndex] = new Vector3(surface.x - verticesEposelong, z, surface.y - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(maxX + verticesEposelong, z, surface.y - verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(maxX + verticesEposelong, z, maxY + verticesEposelong) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(surface.x - verticesEposelong, z, maxY + verticesEposelong) + worldAnchor;
            }
        }

        void GetVerticesBreak(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;
                vertices[verticesIndex] = new Vector3(surface.x - verticesEposelong, maxY + verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(maxX + verticesEposelong, maxY + verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(maxX + verticesEposelong, surface.y - verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(surface.x - verticesEposelong, surface.y - verticesEposelong, z) + worldAnchor;
            }
        }

        void GetVerticesFront(Vector3[] vertices, IList<VoxelSurfaceData> surfaceData, int startIndex)
        {
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z + 1;

                int verticesIndex = surfaceIndex * 4 + startIndex;
                surface.index = verticesIndex;

                vertices[verticesIndex] = new Vector3(maxX + verticesEposelong, maxY + verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 1] = new Vector3(surface.x - verticesEposelong, maxY + verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 2] = new Vector3(surface.x - verticesEposelong, surface.y - verticesEposelong, z) + worldAnchor;
                vertices[verticesIndex + 3] = new Vector3(maxX + verticesEposelong, surface.y - verticesEposelong, z) + worldAnchor;
            }
        }

        Vector3[] Get_Vertices(VoxelDirection a_udlrfb, int a_MaxX, int a_MaxY, int a_MinX, int a_MinY, int z)
        {
            Vector3[] return_Vector3s = null;
            switch (a_udlrfb)
            {
                case VoxelDirection.Right:
                    return_Vector3s = new Vector3[]{
                            new Vector3(z + 1,a_MaxY + verticesEposelong ,a_MinX - verticesEposelong),
                            new Vector3(z + 1,a_MaxY + verticesEposelong ,a_MaxX + verticesEposelong),
                            new Vector3(z + 1,a_MinY - verticesEposelong ,a_MaxX + verticesEposelong),
                            new Vector3(z + 1,a_MinY - verticesEposelong ,a_MinX - verticesEposelong)
               };
                    break;
                case VoxelDirection.Left:
                    return_Vector3s = new Vector3[]{
                            new Vector3(z,a_MinY - verticesEposelong ,a_MinX - verticesEposelong),
                            new Vector3(z,a_MinY - verticesEposelong ,a_MaxX + verticesEposelong),
                            new Vector3(z,a_MaxY + verticesEposelong ,a_MaxX + verticesEposelong),
                            new Vector3(z,a_MaxY + verticesEposelong ,a_MinX - verticesEposelong)
               };
                    break;
                case VoxelDirection.Up:
                    return_Vector3s = new Vector3[]{
                            new Vector3(a_MinX - verticesEposelong ,z + 1, a_MaxY + verticesEposelong),
                            new Vector3(a_MaxX + verticesEposelong ,z + 1, a_MaxY + verticesEposelong),
                            new Vector3(a_MaxX + verticesEposelong ,z + 1, a_MinY - verticesEposelong),
                            new Vector3(a_MinX - verticesEposelong ,z + 1, a_MinY - verticesEposelong)
                 };
                    break;
                case VoxelDirection.Down:
                    return_Vector3s = new Vector3[]{
                            new Vector3(a_MinX - verticesEposelong, z, a_MinY - verticesEposelong),
                            new Vector3(a_MaxX + verticesEposelong, z, a_MinY - verticesEposelong),
                            new Vector3(a_MaxX + verticesEposelong, z, a_MaxY + verticesEposelong),
                            new Vector3(a_MinX - verticesEposelong, z, a_MaxY + verticesEposelong)
                     };
                    break;
                case VoxelDirection.Front:
                    return_Vector3s = new Vector3[]{
                            new Vector3(a_MinX - verticesEposelong,a_MinY - verticesEposelong ,z + 1),
                            new Vector3(a_MaxX + verticesEposelong,a_MinY - verticesEposelong ,z + 1),
                            new Vector3(a_MaxX + verticesEposelong,a_MaxY + verticesEposelong ,z + 1),
                            new Vector3(a_MinX - verticesEposelong,a_MaxY ,z + 1)
               };
                    break;
                case VoxelDirection.Break:
                    return_Vector3s = new Vector3[]{
                            new Vector3(a_MinX - verticesEposelong,a_MaxY + verticesEposelong ,z),
                            new Vector3(a_MaxX + verticesEposelong,a_MaxY + verticesEposelong ,z),
                            new Vector3(a_MaxX + verticesEposelong,a_MinY - verticesEposelong ,z),
                            new Vector3(a_MinX - verticesEposelong,a_MinY - verticesEposelong ,z)
               };
                    break;
                default:
                    break;
            }
            return return_Vector3s;
        }

        Vector2[] GetUVs(IList<VoxelSurfaceData> surfaceData, float overWidth, float overHeigth)
        {
            Vector2[] uvs = new Vector2[surfaceData.Count * 4];
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                var surface = surfaceData[surfaceIndex];
                int maxY = surface.y + surface.h;
                int maxX = surface.x + surface.w;
                int z = surface.z + 1;
                uvs[surface.index] = new Vector2((surface.x + uvEposelong) / overWidth, (maxY - uvEposelong) / overHeigth);
                uvs[surface.index + 1] = new Vector2((maxX - uvEposelong) / overWidth, (maxY - uvEposelong) / overHeigth);
                uvs[surface.index + 2] = new Vector2((maxX - uvEposelong) / overWidth, (surface.y + uvEposelong) / overHeigth);
                uvs[surface.index + 3] = new Vector2((surface.x + uvEposelong) / overWidth, (surface.y + uvEposelong) / overHeigth);
            }
            return uvs;
        }
        Vector2[] GetUVsSurfaceIndex(IList<VoxelSurfaceData> surfaceData, float overWidth, float overHeigth)
        {
            Vector2[] uvs = new Vector2[surfaceData.Count * 4 - bufferAllAddTextureSize * 4];
            for (int surfaceIndex = 0, length = surfaceData.Count; surfaceIndex < length; surfaceIndex++)
            {
                VoxelSurfaceData surface = surfaceData[surfaceIndex];
                if (surface.index != -1)
                {
                    int maxY = surface.y + surface.h;
                    int maxX = surface.x + surface.w;
                    int z = surface.z + 1;
                    uvs[surface.index] = new Vector2((surface.x + uvEposelong) / overWidth, (maxY - uvEposelong) / overHeigth);
                    uvs[surface.index + 1] = new Vector2((maxX - uvEposelong) / overWidth, (maxY - uvEposelong) / overHeigth);
                    uvs[surface.index + 2] = new Vector2((maxX - uvEposelong) / overWidth, (surface.y + uvEposelong) / overHeigth);
                    uvs[surface.index + 3] = new Vector2((surface.x + uvEposelong) / overWidth, (surface.y + uvEposelong) / overHeigth);
                }
            }
            return uvs;
        }


        /// <summary>
        /// 对VoxelSurfaceData进行降序排序
        /// </summary>
        /// <param name="allSurfaceDatas"></param>
        /// <returns></returns>
        VoxelSurfaceData[] DescendingVoxelSurfaceData(IList<VoxelSurfaceData> allSurfaceDatas, out int maxHeigth, out List<VoxelSurfaceData> oneWList)
        {
            oneWList = new List<VoxelSurfaceData>();
            List<VoxelSurfaceData>[] allSurfaceList = new List<VoxelSurfaceData>[256];
            int maxW = 0;
            int maxH = 0;
            foreach (var surface in allSurfaceDatas)
            {
                if (maxW < surface.w)
                {
                    maxW = surface.w;
                }
                if (maxH < surface.h)
                {
                    maxH = surface.h;
                }
                if (1 == surface.w && 1 == surface.h)
                {
                    oneWList.Add(surface);
                }
                else
                {
                    if (allSurfaceList[surface.w] == null)
                    {
                        allSurfaceList[surface.w] = new List<VoxelSurfaceData>();
                        allSurfaceList[surface.w].Add(surface);
                    }
                    else
                    {
                        allSurfaceList[surface.w].Add(surface);
                    }
                }

            }

            VoxelSurfaceData[] overAllSurfaceList = new VoxelSurfaceData[allSurfaceDatas.Count - oneWList.Count];
            for (int allSurfaceListIndex = 0, overAllSurfaceListIndex = overAllSurfaceList.Length - 1; allSurfaceListIndex <= maxW; allSurfaceListIndex++)
            {
                if (allSurfaceList[allSurfaceListIndex] != null)
                {
                    foreach (VoxelSurfaceData item in allSurfaceList[allSurfaceListIndex])
                    {
                        overAllSurfaceList[overAllSurfaceListIndex] = item;
                        overAllSurfaceListIndex--;
                    }
                }
            }
            maxHeigth = maxH;
            //oneWList = allSurfaceList[1];
            return overAllSurfaceList;
        }

        /// <summary>
        /// 合并图片时的剩余区域
        /// </summary>
        struct MergeImgRegion
        {
            public MergeImgRegion(int x, int y, int w, int h)
            {
                this.x = x;
                this.y = y;
                this.w = w;
                this.h = h;
            }
            public int x;
            public int y;
            public int w;
            public int h;
        }

        /// <summary>
        /// 合并时的列
        /// </summary>
        sealed class MergeImgColumn
        {
            public List<MergeImgRegion> Regions = new List<MergeImgRegion>();

            public bool AddSurfaceData(VoxelSurfaceData surface)
            {
                if (lostH >= surface.h)
                {
                    if (w > surface.w)
                    {
                        surface.y = nowH;
                        surface.x = this.x;
                        lostH = lostH - surface.h;
                        nowH += surface.h;
                        MergeImgRegion region = new MergeImgRegion(surface.x + surface.w, surface.y, this.w - surface.w, surface.h);
                        Regions.Add(region);
                        return true;
                    }
                    else if (w == surface.w)
                    {
                        surface.y = nowH;
                        surface.x = this.x;
                        lostH = lostH - surface.h;
                        nowH += surface.h;
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                for (int i = Regions.Count - 1; i >= 0; i--)
                {
                    if (Regions[i].w >= surface.w)
                    {
                        if (Regions[i].h >= surface.h)
                        {
                            surface.x = Regions[i].x;
                            surface.y = Regions[i].y;
                            Regions.RemoveAt(i);
                            return true;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                return false;

            }

            public MergeImgColumn(VoxelSurfaceData surface, int maxHeigth, int x)
            {
                this.x = x;
                surface.x = x;
                surface.y = 0;
                this.w = surface.w;
                this.lostH = maxHeigth - surface.h;
                nowH = surface.h;
            }
            public int x;
            public int lostH;
            public int nowH;
            public int w;
        }

    }
}
